home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
dnsconf
/
primary.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-27
|
12KB
|
532 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "dnsconf.h"
#include "internal.h"
#include "../netconf/netconf.h"
#include "dnsconf.m"
static DNSCONF_HELP_FILE help_primary("primary");
/*
Used to read back an existing configuration
*/
PUBLIC PRIMARY::PRIMARY(
const char *_domain,
const char *_file, // File used to store the configuration
const char *named_dir) // Default directory for configuration files
{
domain.setfrom (_domain);
file.setfrom (_file);
origins.read (named_dir,_file,_domain);
domainv.setfrom (_domain);
isrev = 0;
}
PUBLIC PRIMARY::PRIMARY()
{
isrev = 0;
}
/*
Update the domain name from the visual one.
*/
PUBLIC VIRTUAL void PRIMARY::setfromv()
{
domain.setfrom (domainv);
}
/*
Used to read back an existing configuration
*/
PUBLIC PRIMARY_REV::PRIMARY_REV(
const char *_domain,
const char *_file, // File used to store the configuration
const char *named_dir) // Default directory for configuration files
: PRIMARY(_domain,_file,named_dir)
{
IP_ADDR ipa;
ipa.setfrom (_domain);
ipa.reverse ();
ipa.shift();
domainv.setfrom (ipa.get());
isrev = 1;
}
PUBLIC PRIMARY_REV::PRIMARY_REV()
{
}
/*
Update the domain name from the visual one.
*/
PUBLIC void PRIMARY_REV::setfromv()
{
IP_ADDR ipa;
ipa.setfrom (domainv.get());
char buf[30];
ipa.setrev (buf);
domain.setfrom (buf);
}
/*
Return != if any component of the PRIMARY was modified
*/
PUBLIC int PRIMARY::was_modified()
{
int ret = ARRAY_OBJ::was_modified();
if (!ret){
ret = origins.was_modified();
}
return ret;
}
/*
Return != 0 if the PRIMARY describe the reverse mapping of an
IP network (x.y,z.in-addr.arpa)
*/
PUBLIC VIRTUAL int PRIMARY::is_reverse()
{
return 0;
}
/*
Return != 0 if the PRIMARY describe the reverse mapping of an
IP network (x.y,z.in-addr.arpa)
*/
PUBLIC int PRIMARY_REV::is_reverse()
{
return 1;
}
/*
Locate all IP number in use in a domain.
Return the number added to adrs
*/
PUBLIC int PRIMARY::getalladr(IP_ADDRS &adrs)
{
int ret = 0;
for (int i=0; i<origins.getnb(); i++){
ret += origins.getitem(i)->getalladr(adrs);
}
return ret;
}
/*
Find the first record of a certain type in the PRIMARY
Returne NULL if not found.
*/
PRIVATE RECORD *PRIMARY::getfirst(RECORD_TYPE rtype)
{
RECORD *ret = NULL;
for (int i=0; ret == NULL && i<origins.getnb(); i++){
ORIGIN *ori = origins.getitem(i);
for (int o=0; o<ori->tbrec.getnb(); o++){
RECORD *rec = ori->tbrec.getitem(o);
if (rec->is(rtype)){
ret = rec;
break;
}
}
}
return ret;
}
/*
Find the (first) soa record of a primary
Return NULL if it can be found.
*/
PROTECTED RECORD_IN_SOA *PRIMARY::getsoa()
{
return (RECORD_IN_SOA*)getfirst(RTYPE_SOA);
}
/*
Find all the NS records for a name.
Return the number of record found.
*/
PUBLIC int PRIMARY::getns(
SSTRING &dom,
RECORDS &recs)
{
FQHOST fq (dom);
return locate_left (fq,RTYPE_NS,recs);
}
/*
Find all the NS records for a name.
Return the number of record found.
*/
PUBLIC int PRIMARY::getns(
SSTRING &dom,
SSTRINGS &strs)
{
RECORDS recs;
int nb = getns (dom,recs);
for (int i=0; i<nb; i++){
RECORD_IN_NS *ns = (RECORD_IN_NS*)recs.getitem(i);
strs.add (new SSTRING (ns->ns));
}
return nb;
}
/*
Find all the MX records for name.
Return the number of record found.
*/
PUBLIC int PRIMARY::getmx(
SSTRING &dom,
RECORDS &recs)
{
FQHOST fq (dom);
return locate_left (fq,RTYPE_MX,recs);
}
/*
Find all the MX records for a name.
Return the number of record found.
*/
PUBLIC int PRIMARY::getmx(
SSTRING &dom,
SSTRINGS &strs)
{
RECORDS recs;
int nb = getmx (dom,recs);
for (int i=0; i<nb; i++){
RECORD_IN_MX *mx = (RECORD_IN_MX*)recs.getitem(i);
strs.add (new SSTRING (mx->servname));
}
return nb;
}
/*
Find all the A records for a name.
Return the number of record found.
*/
PUBLIC int PRIMARY::geta(
SSTRING &dom,
RECORDS &recs)
{
FQHOST fq (dom);
return locate_left (fq,RTYPE_A,recs);
}
/*
Find all the A records for a name.
Return the number of record found.
*/
PUBLIC int PRIMARY::geta(
SSTRING &dom,
IP_ADDRS &adrs)
{
RECORDS recs;
int nb = geta (dom,recs);
for (int i=0; i<nb; i++){
RECORD_IN_A *a = (RECORD_IN_A*)recs.getitem(i);
adrs.add (new IP_ADDR (a->addr));
}
return nb;
}
/*
Find the CNAME record for a name.
Return -1 if not found. cname will be empty.
*/
PUBLIC int PRIMARY::getcname(
SSTRING &dom,
SSTRING &cname)
{
FQHOST fq (dom);
RECORDS recs;
int nb = locate_left (fq,RTYPE_CNAME,recs);
cname.setfrom ("");
int ret = -1;
if (nb > 0){
RECORD_IN_CNAME *a = (RECORD_IN_CNAME*)recs.getitem(0);
cname.setfrom (a->name);
ret = 0;
}
return ret;
}
/*
Increment if needed the serial number of the SOA
This function may be called several time. The serial number
will be incremented only once per session though.
*/
PUBLIC void PRIMARY::updatesoa()
{
if (origins.was_modified()){
RECORD_IN_SOA *soa = getsoa();
if (soa != NULL) soa->update(domain.get());
}
}
/*
Write the records of the domain and the entry in named.boot
Return -1 if any error.
*/
PUBLIC int PRIMARY::write (FILE *fout, const char *named_dir) const
{
int ret = origins.save (named_dir,file.get());
fprintf (fout,"primary\t%s\t%s\n",domain.get(),file.get());
return ret;
}
/*
Add a record in the PRIMARY.
The record is record relative to the main origin of the primary.
*/
PUBLIC void PRIMARY::addrec (RECORD *rec)
{
if (origins.getnb()==0){
ORIGIN *ori = new ORIGIN(domain.get());
origins.add (ori);
}
origins.getitem(0)->tbrec.add (rec);
}
/*
Edit the basic specs of a domain.
Return -1 if the user abort edition
Return 0 if the user accepted the changes
Return 1 if the user wish to delete this domain.
*/
PUBLIC int PRIMARY::edit(DNS &dns)
{
THISHOST thost;
DIALOG dia;
dia.newf_str (isrev ? MSG_U(F_NETNUM,"Network number")
: MSG_U(F_DOMAIN,"Domain"),domainv);
RECORD_IN_SOA *soa = getsoa();
SSTRINGS rns;
if (getns(domain,rns) == 0){
rns.add (new SSTRING (thost.getname1()));
}
/* #Specification: dnsconf / main ns records of the domain
dnsconf allows the specification of up to 3 NS
record for a primary.
*/
while (rns.getnb() < 3) rns.add (new SSTRING);
SSTRINGS rmx;
if (getmx(domain,rmx) == 0){
rmx.add (new SSTRING (thost.getname1()));
}
/* #Specification: dnsconf / main mx records of the domain
dnsconf allows the specification of up to 3 MX
records for a primary.
*/
while (rmx.getnb() < 3) rmx.add (new SSTRING);
if (soa == NULL) soa = new RECORD_IN_SOA;
dia.newf_str (MSG_U(F_MAINSERV,"Main server"),soa->machine);
dia.newf_str (MSG_U(F_ADMINMAIL,"Administrator email"),soa->admin);
dia.newf_title ("",MSG_R(F_DNSADV));
int i;
for (i=0; i<rns.getnb(); i++){
dia.newf_str ("",*(rns.getitem(i)));
}
dia.newf_title ("",MSG_R(F_EMAILADV));
for (i=0; i<rmx.getnb(); i++){
dia.newf_str ("",*(rmx.getitem(i)));
}
dia.newf_title ("",MSG_U(F_SECREQ,"Secondaries requirements"));
dia.newf_str (MSG_U(F_REFRESH,"Refresh"),soa->refresh);
dia.newf_str (MSG_U(F_RETRY,"Retry"),soa->retry);
dia.newf_str (MSG_U(F_EXPIRE,"Expire"),soa->expire);
dia.newf_title ("",MSG_U(F_EVERYHOSTS,"Every hosts requirements"));
dia.newf_str (MSG_U(F_TTL,"Time to live"),soa->default_ttl);
int ret = -1;
int nof = 0;
while (1){
MENU_STATUS status = dia.edit (
MSG_U(T_PRIMSPEC,"Primary specification")
,MSG_U(I_PRIMSPEC,"You must enter a domain name\n")
,help_primary.getpath()
,nof
,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL);
if (status == MENU_CANCEL || status == MENU_ESCAPE){
break;
}else if (status == MENU_DEL){
if (xconf_areyousure(MSG_U(Q_DELPRIMARY
,"Confirm deletion of a domain"))){
ret = 1;
break;
}
}else{
if (domainv.is_empty()){
xconf_error(MSG_U(E_NODOMAIN,"Fill at least the domain\n"
"and the first IP address"));
}else{
setfromv();
if (getsoa()==NULL) addrec (soa);
/* #Specification: dnsconf / primary / record file
dnsconf use the domain name as the file name
which will contain the record.
You can change the name in /etc/named.boot and dnsconf
will use this one instead.
*/
if (file.is_empty) file.setfrom (domainv);
dns.setmx (domain,rmx);
dns.setns (domain,rns);
setmodified();
ret = 0;
break;
}
}
}
if (ret != 0) dia.restore();
return ret;
}
PUBLIC PRIMARY *PRIMARYS::getitem (int no) const
{
return (PRIMARY*)ARRAY::getitem(no);
}
/*
Locate all IP number in use in all domain of this DNS.
Return the number added to adrs
*/
PUBLIC int PRIMARYS::getalladr(IP_ADDRS &adrs)
{
int ret = 0;
for (int i=0; i<getnb(); i++){
ret += getitem(i)->getalladr(adrs);
}
return ret;
}
/*
Get a PRIMARY for a fully qualified host.
Get the primary that is the closest to the hostname
(ie: x.y.z.com will select y.z.com instead of z.com if both
domain are defined in this DNS).
Return NULL if not found.
*/
PUBLIC PRIMARY *PRIMARYS::getitem(
FQHOST &fq,
char *hostpart,
int dontitself) // if dontitself != 0
// && fq is itself a domain
// don't select it
{
/* #Specification: dnsconf / matching a primary / closest
When trying to dispatch information about a host
in the DNS, dnsconf try to find the primary which
has the closest match. This means that if a DNS
is a primary for x.y.com and y.com, and dnsconf
dispatch info about the host host.x.y.com, it will
select the domain x.y.com.
On the other end, host.w.y.com will be dispatch
in the domain y.com.
*/
PRIMARY *ret = NULL;
int minlevel = 100;
if (hostpart != NULL) hostpart[0] = '\0';
for (int i=0; i<getnb(); i++){
PRIMARY *pri = getitem(i);
char tmp[200];
int level = fq.is_member(pri->domain.get(),tmp);
if (level > 0 && level < minlevel){
if (!dontitself || strcmp(tmp,"@")!=0){
ret = pri;
minlevel = level;
if (hostpart != NULL) strcpy (hostpart,tmp);
}
}
}
return ret;
}
/*
Get a PRIMARY for a fully qualified host.
Get the primary that is the closest to the hostname
(ie: x.y.z.com will select y.z.com instead of z.com if both
domain are defined in this DNS).
Return NULL if not found.
*/
PUBLIC PRIMARY *PRIMARYS::getitem(FQHOST &fq, char *hostpart)
{
return getitem (fq,hostpart,0);
}
PUBLIC int PRIMARYS::write (FILE *fout, const char *named_dir) const
{
int ret = 0;
for (int i=0; i<getnb(); i++){
if (getitem(i)->write(fout,named_dir) == -1) ret = -1;
}
return ret;
}
PUBLIC VIRTUAL PRIMARY *PRIMARYS::new_PRIMARY()
{
return new PRIMARY;
}
PUBLIC PRIMARY *PRIMARYS_REV::new_PRIMARY()
{
return new PRIMARY_REV;
}
static int cmp_by_name (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2)
{
PRIMARY *s1 = (PRIMARY*)o1;
PRIMARY *s2 = (PRIMARY*)o2;
return s1->domainv.cmp(s2->domainv);
}
/*
Present the list of primarys. Show selectivly the
standard domain primaris or the reverse mapping primarys.
*/
PUBLIC void PRIMARYS::edit(DNS &dns)
{
int choice=0;
while (1){
int nb = getnb();
/* #Specification: domains / edition / sorting
Domain are always sorted before being presented. This changes
the ordering in /etc/named.boot.
*/
sort(cmp_by_name);
DIALOG dia;
for (int i=0; i<nb; i++){
PRIMARY *pri = getitem(i);
dia.new_menuitem (" ",pri->domainv);
}
dia.addwhat (MSG_U(I_ADDPRIM,"add one primary spec"));
MENU_STATUS code = dia.editmenu(
MSG_U(T_PRIMARYS,"Primarys")
,MSG_U(I_PRIMARYS
,"You are allowed to edit/add/remove primaries\n")
,help_primary
,choice,0);
if (code == MENU_QUIT || code == MENU_ESCAPE){
break;
}else if (code == MENU_ADD){
PRIMARY *pri = new_PRIMARY();
add (pri);
if (pri->edit(dns) != 0){
remove_del (pri);
}else{
/* #Specification: dnsconf / new primary / host info
Whenever we add a new primary, we
try to update the basic host information
of this host so the DNS will be
automaticly current.
*/
netconf_updatedns();
dns.write();
}
}else if (choice >= 0 && choice < nb){
PRIMARY *pri = getitem(choice);
int ok = pri->edit(dns);
if (ok >= 0){
if (ok == 1) remove_del(pri);
dns.write();
}
}
}
}